package cn.fan.service;

import cn.fan.constants.DataBaseConstants;
import cn.fan.mapper.UserMapper;
import cn.fan.pojo.User;
import cn.fan.redis.UserRedis;
import cn.fan.utils.Encryption;
import cn.fan.utils.PassJavaJwtTokenUtil;
import cn.fan.utils.R;
import cn.fan.utils.ServletUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class UserService {
    // 更新（添加、删除、获取）失败
    private static final int FAIL = -1;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRedis userRedis;

    @Autowired
    private Encryption encryption;

    @Autowired
    private PassJavaJwtTokenUtil jwtTokenUtil;

    public Long getSysUserId(){
        HttpServletRequest request = ServletUtils.getRequest();
        String userId = jwtTokenUtil.getUserIdFromRequest(request);

        return StringUtils.hasText(userId) ? Long.parseLong(userId) : FAIL;
    }

    public User getSysUser(){
        Long userId=getSysUserId();
        if(userId == FAIL)
            return null;

        User user = userRedis.getById(userId);
        return user;
    }

    public R login(User user) {
        String userId  = user.getId().toString();
        String password = user.getPassword();
        if(!StringUtils.hasText(userId) || !StringUtils.hasText(password))
            return R.error("登录失败");

        User sysUser = userRedis.getById(user.getId());
        if (null == sysUser)
            return R.error("该用户不存在");

        boolean isAuthenticated = encryption.auth(password,sysUser);
        if (!isAuthenticated)
            return R.error("密码错误");

        Map<String, Object> tokenMap = jwtTokenUtil
                .generateTokenAndRefreshToken(userId, sysUser.getUsername());
        return R.ok(tokenMap);
    }

    public void logout() {
        long userId = getSysUserId();
        if(userId != FAIL){
            jwtTokenUtil.moveToken(userId+"");
        }
    }

    public int add(User user){
        long sysUserId = getSysUserId();
        if (sysUserId == FAIL)
            return FAIL;

        String salt = new SecureRandomNumberGenerator().nextBytes().toString();
        String password = encryption.generatePassword(user.getPassword(),salt);
        user.setPassword(password);
        user.setSalt(salt);

        user.setCreateDate(new Date());
        user.setCreateBy(sysUserId);

        int i = userMapper.insert(user);

        userRedis.putByUser(user.getId(),user);
        return i;
    }

    public int delete(Long id) {
        int i = userMapper.deleteById(id);
        userRedis.delete(id);
        return i;
//        return i>DataBaseConstants.NO_DATA ? R.ok() : R.error("无该用户");
    }

    public int edit(User user) {
        long sysUserId = getSysUserId();
        if (sysUserId == FAIL)
            return FAIL;

        User sysUser = getById(user.getId());

        if (null == sysUser)
            return DataBaseConstants.NO_DATA;

        sysUser.setUsername(user.getUsername());
        sysUser.setEmailadd(user.getEmailadd());
        sysUser.setAddress(user.getAddress());

        if(StringUtils.hasText(user.getPassword())){
            String salt = new SecureRandomNumberGenerator().nextBytes().toString();
            String password = encryption.generatePassword(user.getPassword(),salt);
            sysUser.setPassword(password);
            sysUser.setSalt(salt);
        }

        sysUser.setUpdateDate(new Date());
        sysUser.setUpdateBy(sysUserId);

        int i = userMapper.updateById(sysUser);
        userRedis.putByUser(sysUser.getId(),sysUser);
        return i;
    }

    public User getById(Long id){
        return userRedis.getById(id);
    }

    public User getByIdNoPswd(Long id){
        User user = userRedis.getById(id);
        user.setPassword("");
        user.setSalt("");

        return user;
    }

    public List<User> list(Map map){
        LambdaQueryWrapper<User> queryWrapper = getUserLambdaQueryWrapper(map);

        List<User> list=userMapper.selectList(queryWrapper);
        return list;
    }

    public IPage<User> page(Map map,long currentPage,long pageSize){
        IPage<User> page = new Page<>(currentPage,pageSize);

        LambdaQueryWrapper<User> queryWrapper = getUserLambdaQueryWrapper(map);

        IPage<User> userIPage = userMapper.selectPage(page, queryWrapper);
        return userIPage;
    }

    private LambdaQueryWrapper<User> getUserLambdaQueryWrapper(Map map) {
        LambdaQueryWrapper<User> queryWrapper= new LambdaQueryWrapper<User>();

        if (null == map || map.size() == 0)
            return queryWrapper;

        if(null != map.get("user")){
            String userJson = JSON.toJSONString(map.get("user"));
            User user = JSONObject.parseObject(userJson,User.class);

            queryWrapper.eq( null != user.getId(),
                    User::getId,
                    user.getId());
            queryWrapper.like(StringUtils.hasText(user.getUsername()),
                    User::getUsername,
                    user.getUsername());
            queryWrapper.like(StringUtils.hasText(user.getEmailadd()),
                    User::getEmailadd,
                    user.getEmailadd());
            queryWrapper.like(StringUtils.hasText(user.getAddress()),
                    User::getAddress,
                    user.getAddress());
            queryWrapper.eq(user.getCreateBy()!=null,
                    User::getCreateBy,
                    user.getCreateBy());
            queryWrapper.eq(user.getUpdateBy()!=null,
                    User::getUpdateBy,
                    user.getUpdateBy());
        }

        Object startDate = map.get("startDate");
        queryWrapper.ge( (null!=startDate && StringUtils.hasText(startDate.toString())) ,
                User::getCreateDate,
                startDate);
        Object endDate = map.get("endDate");
        queryWrapper.le( (null!=endDate && StringUtils.hasText(endDate.toString())) ,
                User::getCreateDate,
                endDate);

        Object upStartDate = map.get("upStartDate");
        queryWrapper.ge( (null!=upStartDate && StringUtils.hasText(upStartDate.toString())) ,
                User::getUpdateDate,
                upStartDate);
        Object uEndDate = map.get("uEndDate");
        queryWrapper.le( (null!=uEndDate && StringUtils.hasText(uEndDate.toString())) ,
                User::getUpdateDate,
                uEndDate);

        return queryWrapper;
    }

}
